/**
*	@file StallComputer.cpp
*
*	@brief compute stall number for simple
*
*	@author li yuchen
*
*	@date 1/28/2011
*/
#include "StallCompute.h"
#include "ProcTable.h"
#include "VarTable.h"
#include "Modifies.h"
#include "StmtTable.h"
#include "Follows.h"
#include "Uses.h"
#include <iostream>

int CalculateStall(){
	int stall_num = 0;
	vector<bool> visited(StmtTable::GetSize(),false);
	for(int i = 0; i < ProcTable::GetSize();i++){
		GNode* traverser = ProcTable::GetProcCFGRoot(i+1);
		stack<GNode*> gnode_stack;
		gnode_stack.push(traverser);
		while(!gnode_stack.empty()){
			traverser = gnode_stack.top();
			gnode_stack.pop();
			if(visited[traverser->stmt_num-1]) continue;
			visited[traverser->stmt_num-1] = true;
			switch(traverser->g_type){
			case ASSIGN_TYPE:
			{
				VarIdx mod_var_idx = StmtTable::GetStmtTNode(traverser->stmt_num)->child->value;
				if(traverser->next_a != NULL && Follows::IsFollows(traverser->stmt_num,traverser->next_a->stmt_num)){
					switch(traverser->next_a->g_type){
					case ASSIGN_TYPE:
						if(Uses::IsUsesS(traverser->next_a->stmt_num,mod_var_idx)){
							stall_num++;
							//cout << "stall between " << traverser->stmt_num << " and " << traverser->next_a->stmt_num << endl;
						}
						break;
					case WHILE_TYPE:
					case IF_TYPE:
						if(StmtTable::GetStmtTNode(traverser->next_a->stmt_num)->child->value == mod_var_idx){
							stall_num++;
							//cout << "stall between " << traverser->stmt_num << " and " << traverser->next_a->stmt_num << endl;
						}
						break;
					case CALL_TYPE:
						break;
					default:
						cout << "stall compute has the type error" << endl;
						getchar();
						exit(1);
					}
					gnode_stack.push(traverser->next_a);
				}
				break;
			}
			case WHILE_TYPE:
				gnode_stack.push(traverser->next_a);
				if(traverser->next_b != NULL) gnode_stack.push(traverser->next_b);
				break;
			case IF_TYPE:
				gnode_stack.push(traverser->next_a);
				gnode_stack.push(traverser->next_b);
				break;
			case CALL_TYPE:
				break;
			default:
				cout << "stall compute has the type error" << endl;
				getchar();
				exit(1);
			}
		}// end of while
	}
	return stall_num;
}